home *** CD-ROM | disk | FTP | other *** search
/ ftp.mactech.com 2010 / ftp.mactech.com.tar / ftp.mactech.com / macintosh-c / macc-carbon-demos-nonbinhex.sit / macc-carbon-demos-nonbinhex / chap23-demo-classic events / Drag.c < prev    next >
C/C++ Source or Header  |  2001-05-31  |  30KB  |  1,176 lines

  1. // *******************************************************************************************
  2. // Drag.c
  3. // *******************************************************************************************
  4.  
  5. // ………………………………………………………………………………………………………………………………………………………………………………………………………………………… includes
  6.  
  7. #include "Drag.h"
  8.  
  9. // …………………………………………………………………………………………………………………………………………………………………………………………………… global variables
  10.  
  11. ControlActionUPP                gScrollActionFunctionUPP;
  12. TEClickLoopUPP                    gCustomClickLoopUPP;
  13. DragTrackingHandlerUPP    gDragTrackingHandlerUPP;
  14. DragReceiveHandlerUPP        gDragReceiveHandlerUPP;
  15. Boolean                                    gRunningOnX = false;
  16. Boolean                                    gDone;
  17. RgnHandle                                gCursorRegion;
  18. SInt16                                    gNumberOfWindows                = 0;
  19. SInt16                                     gOldControlValue;
  20. Boolean                                    gEnableDragUndoRedoItem    = false;
  21. Boolean                                    gUndoFlag;
  22.  
  23. // ************************************************************************************** main
  24.  
  25. void  main(void)
  26. {
  27.     MenuBarHandle    menubarHdl;
  28.     SInt32                response;
  29.     MenuRef                menuRef;
  30.  
  31.     // ……………………………………………………………………………………………………………………………………………………………………………………………… do preliminaries
  32.  
  33.     doPreliminaries();
  34.  
  35.     // …………………………………………………………………………………………………………………………………………… create universal procedure pointers
  36.  
  37.     gScrollActionFunctionUPP = NewControlActionUPP((ControlActionProcPtr) scrollActionFunction);
  38.     gCustomClickLoopUPP      = NewTEClickLoopUPP((TEClickLoopProcPtr) customClickLoop);
  39.  
  40.     gDragTrackingHandlerUPP  = NewDragTrackingHandlerUPP((DragTrackingHandlerProcPtr)
  41.                                                                                                              dragTrackingHandler);
  42.     gDragReceiveHandlerUPP   = NewDragReceiveHandlerUPP((DragReceiveHandlerProcPtr)
  43.                                                                                                             dragReceiveHandler);
  44.  
  45.     // ……………………………………………………………………………………………………………………………………………………………………… set up menu bar and menus
  46.  
  47.     menubarHdl = GetNewMBar(rMenubar);
  48.     if(menubarHdl == NULL)
  49.         doErrorAlert(eMenuBar);
  50.     SetMenuBar(menubarHdl);
  51.     DrawMenuBar();
  52.  
  53.     Gestalt(gestaltMenuMgrAttr,&response);
  54.     if(response & gestaltMenuMgrAquaLayoutMask)
  55.     {
  56.         menuRef = GetMenuRef(mFile);
  57.         if(menuRef != NULL)
  58.         {
  59.             DeleteMenuItem(menuRef,iQuit);
  60.             DeleteMenuItem(menuRef,iQuit - 1);
  61.         }
  62.  
  63.         gRunningOnX = true;
  64.     }
  65.  
  66.     // …………………………………………………………………………………………………………………………………………………………………………… open an untitled window
  67.  
  68.     doNewDocWindow();
  69.  
  70.     // ………………………………………………………………………………………………………………………………………………………………………………………………… enter eventLoop
  71.  
  72.     eventLoop();
  73. }
  74.  
  75. // *************************************************************************** doPreliminaries
  76.  
  77. void  doPreliminaries(void)
  78. {
  79.     OSErr    osError;
  80.  
  81.     MoreMasterPointers(192);
  82.     InitCursor();
  83.     FlushEvents(everyEvent,0);
  84.  
  85.     osError = AEInstallEventHandler(kCoreEventClass,kAEQuitApplication,
  86.                                                         NewAEEventHandlerUPP((AEEventHandlerProcPtr) quitAppEventHandler),
  87.                                                         0L,false);
  88.     if(osError != noErr)
  89.         ExitToShell();
  90. }
  91.  
  92. // **************************************************************************** doQuitAppEvent
  93.  
  94. OSErr  quitAppEventHandler(AppleEvent *appEvent,AppleEvent *reply,SInt32 handlerRefcon)
  95. {
  96.     OSErr            osError;
  97.     DescType    returnedType;
  98.     Size            actualSize;
  99.  
  100.     osError = AEGetAttributePtr(appEvent,keyMissedKeywordAttr,typeWildCard,&returnedType,NULL,0,
  101.                                                             &actualSize);
  102.  
  103.     if(osError == errAEDescNotFound)
  104.     {
  105.         gDone = true;
  106.         osError = noErr;
  107.     } 
  108.     else if(osError == noErr)
  109.         osError = errAEParamMissed;
  110.  
  111.     return osError;
  112. }
  113.  
  114. // ********************************************************************************* eventLoop
  115.  
  116. void  eventLoop(void)
  117. {
  118.     EventRecord    eventStructure;
  119.     Boolean            gotEvent;
  120.     SInt32            sleepTime;
  121.  
  122.     gDone = false;
  123.     gCursorRegion = NewRgn();
  124.     doAdjustCursor(FrontWindow());
  125.     sleepTime = GetCaretTime();
  126.  
  127.     while(!gDone)
  128.     {
  129.         gotEvent = WaitNextEvent(everyEvent,&eventStructure,sleepTime,gCursorRegion);
  130.  
  131.         if(gotEvent)
  132.             doEvents(&eventStructure);
  133.         else
  134.         {
  135.             if(eventStructure.what == nullEvent)
  136.                 if(gNumberOfWindows > 0)
  137.                     doIdle();
  138.         }
  139.     }
  140. }
  141.  
  142. // ************************************************************************************ doIdle
  143.  
  144. void  doIdle(void)
  145. {
  146.     docStructurePointer    docStrucPtr;
  147.     WindowRef                        windowRef;
  148.  
  149.     windowRef = FrontWindow();
  150.  
  151.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));
  152.     if(docStrucPtr != NULL)
  153.         TEIdle(docStrucPtr->textEditStrucHdl);
  154. }    
  155.  
  156. // ********************************************************************************** doEvents
  157.  
  158. void    doEvents(EventRecord *eventStrucPtr)
  159. {
  160.     WindowRef                windowRef;
  161.     WindowPartCode    partCode;
  162.     SInt8                        charCode;
  163.  
  164.     switch(eventStrucPtr->what)
  165.     {
  166.         case kHighLevelEvent:
  167.             AEProcessAppleEvent(eventStrucPtr);
  168.             break;
  169.  
  170.         case mouseDown:
  171.             partCode = FindWindow(eventStrucPtr->where,&windowRef);
  172.             switch(partCode)
  173.             {
  174.                 case inMenuBar:
  175.                     doAdjustMenus();
  176.                     doMenuChoice(MenuSelect(eventStrucPtr->where));
  177.                     break;
  178.  
  179.                 case inContent:
  180.                     if(windowRef != FrontWindow())
  181.                         SelectWindow(windowRef);
  182.                     else
  183.                         doInContent(eventStrucPtr);
  184.                     break;
  185.  
  186.                 case inDrag:
  187.                     DragWindow(windowRef,eventStrucPtr->where,NULL);
  188.                     doAdjustCursor(windowRef);
  189.                     break;
  190.  
  191.                 case inGoAway:
  192.                     if(TrackGoAway(windowRef,eventStrucPtr->where))
  193.                         doCloseWindow(FrontWindow());
  194.                     break;
  195.             }
  196.             break;
  197.  
  198.         case keyDown:
  199.             charCode = eventStrucPtr->message & charCodeMask;
  200.             if((eventStrucPtr->modifiers & cmdKey) != 0)
  201.             {
  202.                 doAdjustMenus();
  203.                 doMenuChoice(MenuEvent(eventStrucPtr));
  204.             }
  205.             else
  206.                 doKeyEvent(charCode);
  207.             break;
  208.  
  209.         case autoKey:
  210.             charCode = eventStrucPtr->message & charCodeMask;
  211.             if((eventStrucPtr->modifiers & cmdKey) == 0)
  212.                 doKeyEvent(charCode);
  213.             break;
  214.  
  215.         case updateEvt:
  216.             doUpdate(eventStrucPtr);
  217.             break;
  218.  
  219.         case activateEvt:
  220.             doActivate(eventStrucPtr);
  221.             break;
  222.  
  223.         case osEvt:
  224.             doOSEvent(eventStrucPtr);
  225.             break;
  226.     }
  227. }
  228.  
  229. // ******************************************************************************** doKeyEvent
  230.  
  231. void  doKeyEvent(SInt8 charCode)
  232. {
  233.     WindowRef                        windowRef;
  234.     docStructurePointer    docStrucPtr;
  235.     TEHandle                        textEditStrucHdl;
  236.     SInt16                            selectionLength;
  237.  
  238.     windowRef = FrontWindow();
  239.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));
  240.     textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  241.  
  242.     gEnableDragUndoRedoItem = false;
  243.  
  244.     if(charCode == kTab)
  245.     {
  246.         // Do tab key handling here if required.
  247.     }
  248.     else if(charCode == kDel)
  249.     {
  250.         selectionLength = doGetSelectLength(textEditStrucHdl);
  251.         if(selectionLength == 0)
  252.             (*textEditStrucHdl)->selEnd += 1;
  253.         TEDelete(textEditStrucHdl);
  254.         doAdjustScrollbar(windowRef);
  255.     }
  256.     else
  257.     {
  258.         selectionLength = doGetSelectLength(textEditStrucHdl);
  259.         if(((*textEditStrucHdl)->teLength - selectionLength + 1) < kMaxTELength)
  260.         {
  261.             TEKey(charCode,textEditStrucHdl);
  262.             doAdjustScrollbar(windowRef);
  263.         }
  264.         else
  265.             doErrorAlert(eExceedChara);
  266.     }
  267. }
  268.  
  269. // ********************************************************************** scrollActionFunction
  270.  
  271. void  scrollActionFunction(ControlRef controlRef,SInt16 partCode)
  272. {
  273.     WindowRef                        windowRef;
  274.     docStructurePointer    docStrucPtr;
  275.     TEHandle                        textEditStrucHdl;
  276.     SInt16                            linesToScroll;
  277.     SInt16                            controlValue, controlMax;
  278.  
  279.     windowRef = GetControlOwner(controlRef);
  280.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));;
  281.     textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  282.  
  283.     controlValue = GetControlValue(controlRef);
  284.     controlMax = GetControlMaximum(controlRef);
  285.  
  286.     if(partCode)
  287.     {
  288.         if(partCode != kControlIndicatorPart)
  289.         {
  290.             switch(partCode)
  291.             {
  292.                 case kControlUpButtonPart:
  293.                 case kControlDownButtonPart:
  294.                     linesToScroll = 1;
  295.                     break;
  296.                 
  297.                 case kControlPageUpPart:
  298.                 case kControlPageDownPart:
  299.                     linesToScroll = (((*textEditStrucHdl)->viewRect.bottom - 
  300.                                                     (*textEditStrucHdl)->viewRect.top) /
  301.                                                     (*textEditStrucHdl)->lineHeight) - 1;
  302.                     break;
  303.             }
  304.  
  305.             if((partCode == kControlDownButtonPart) || (partCode == kControlPageDownPart))
  306.                 linesToScroll = -linesToScroll;
  307.  
  308.             linesToScroll = controlValue - linesToScroll;
  309.             if(linesToScroll < 0)
  310.                 linesToScroll = 0;
  311.             else if(linesToScroll > controlMax)
  312.                 linesToScroll = controlMax;
  313.  
  314.             SetControlValue(controlRef,linesToScroll);
  315.  
  316.             linesToScroll = controlValue - linesToScroll;
  317.         }
  318.         else
  319.         {
  320.             linesToScroll = gOldControlValue - controlValue;
  321.             gOldControlValue = controlValue;
  322.         }
  323.  
  324.         if(linesToScroll != 0)
  325.             TEScroll(0,linesToScroll * (*textEditStrucHdl)->lineHeight,textEditStrucHdl);
  326.     }
  327. }
  328.  
  329. // ******************************************************************************* doInContent
  330.  
  331. void  doInContent(EventRecord *eventStrucPtr)
  332. {
  333.     WindowRef                        windowRef;
  334.     docStructurePointer    docStrucPtr;
  335.     TEHandle                        textEditStrucHdl;
  336.     Point                                mouseXY;
  337.     ControlRef                    controlRef;
  338.     SInt16                            partCode;
  339.     RgnHandle                        hiliteRgn;
  340.     OSErr                                osError;
  341.     Boolean                            shiftKeyPosition = false;
  342.  
  343.     windowRef = FrontWindow();
  344.     docStrucPtr = (docStructurePointer) GetWRefCon(windowRef);
  345.     textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  346.  
  347.     mouseXY = eventStrucPtr->where;
  348.     SetPortWindowPort(windowRef);
  349.     GlobalToLocal(&mouseXY);
  350.  
  351.     if((partCode = FindControl(mouseXY,windowRef,&controlRef)) != 0)
  352.     {
  353.         gOldControlValue = GetControlValue(controlRef);
  354.         TrackControl(controlRef,mouseXY,gScrollActionFunctionUPP);
  355.     }
  356.     else if(PtInRect(mouseXY,&(*textEditStrucHdl)->viewRect))
  357.     {
  358.         hiliteRgn = NewRgn();
  359.  
  360.         TEGetHiliteRgn(hiliteRgn,textEditStrucHdl);
  361.  
  362.         if(!EmptyRgn(hiliteRgn) && PtInRgn(mouseXY,hiliteRgn))
  363.         {
  364.             if(WaitMouseMoved(eventStrucPtr->where))
  365.             {
  366.                 osError = doStartDrag(eventStrucPtr,hiliteRgn,textEditStrucHdl);
  367.                 if(osError != noErr)
  368.                     doErrorAlert(eDrag);
  369.             }    
  370.         }
  371.         else
  372.         {
  373.             if((eventStrucPtr->modifiers & shiftKey) != 0)
  374.                 shiftKeyPosition = true;
  375.             TEClick(mouseXY,shiftKeyPosition,textEditStrucHdl);
  376.  
  377.             gEnableDragUndoRedoItem = false;        
  378.  
  379.             doAdjustCursor(windowRef);
  380.         }
  381.  
  382.         DisposeRgn(hiliteRgn);
  383.     }
  384. }
  385.  
  386. // ********************************************************************************** doUpdate
  387.  
  388. void    doUpdate(EventRecord *eventStrucPtr)
  389. {
  390.     WindowRef                        windowRef;
  391.     docStructurePointer    docStrucPtr;
  392.     TEHandle                        textEditStrucHdl;
  393.     GrafPtr                            oldPort;
  394.     RgnHandle                        visibleRegionHdl = NewRgn();
  395.     Rect                                portRect;
  396.  
  397.     windowRef = (WindowRef) eventStrucPtr->message;
  398.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));
  399.     textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  400.     
  401.     GetPort(&oldPort);
  402.     SetPortWindowPort(windowRef);
  403.  
  404.     BeginUpdate((WindowRef) eventStrucPtr->message);
  405.  
  406.     GetPortVisibleRegion(GetWindowPort(windowRef),visibleRegionHdl);
  407.   EraseRgn(visibleRegionHdl);
  408.  
  409.     UpdateControls(windowRef,visibleRegionHdl);
  410.  
  411.     GetWindowPortBounds(windowRef,&portRect);
  412.     TEUpdate(&(*textEditStrucHdl)->viewRect,textEditStrucHdl);
  413.  
  414.     EndUpdate((WindowRef) eventStrucPtr->message);
  415.  
  416.     DisposeRgn(visibleRegionHdl);
  417.     SetPort(oldPort);
  418. }
  419.  
  420. // ******************************************************************************** doActivate
  421.  
  422. void  doActivate(EventRecord *eventStrucPtr)
  423. {
  424.     WindowRef    windowRef;
  425.     Boolean        becomingActive;
  426.  
  427.     windowRef = (WindowRef) eventStrucPtr->message;
  428.     becomingActive = ((eventStrucPtr->modifiers & activeFlag) == activeFlag);
  429.     doActivateDocWindow(windowRef,becomingActive);
  430. }
  431.  
  432. // *********************************************************************** doActivateDocWindow
  433.  
  434. void  doActivateDocWindow(WindowRef windowRef,Boolean becomingActive)
  435. {
  436.     docStructurePointer    docStrucPtr;
  437.     TEHandle                        textEditStrucHdl;
  438.  
  439.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));
  440.     textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  441.  
  442.     if(becomingActive)
  443.     {
  444.         SetPortWindowPort(windowRef);
  445.  
  446.         (*textEditStrucHdl)->viewRect.bottom = ((((*textEditStrucHdl)->viewRect.bottom -
  447.                                                                                         (*textEditStrucHdl)->viewRect.top) / 
  448.                                                                                         (*textEditStrucHdl)->lineHeight) * 
  449.                                                                                         (*textEditStrucHdl)->lineHeight) + 
  450.                                                                                         (*textEditStrucHdl)->viewRect.top;
  451.         (*textEditStrucHdl)->destRect.bottom = (*textEditStrucHdl)->viewRect.bottom;
  452.  
  453.         TEActivate(textEditStrucHdl);
  454.         ActivateControl(docStrucPtr->vScrollbarRef);
  455.         doAdjustScrollbar(windowRef);
  456.         doAdjustCursor(windowRef);
  457.     }
  458.     else
  459.     {
  460.         TEDeactivate(textEditStrucHdl);
  461.         DeactivateControl(docStrucPtr->vScrollbarRef);
  462.     }
  463. }
  464.  
  465. // ********************************************************************************* doOSEvent
  466.  
  467. void    doOSEvent(EventRecord *eventStrucPtr)
  468. {
  469.     switch((eventStrucPtr->message >> 24) & 0x000000FF)
  470.     {
  471.         case suspendResumeMessage:
  472.             if((eventStrucPtr->message & resumeFlag) == 1)
  473.                 SetThemeCursor(kThemeArrowCursor);
  474.             break;
  475.  
  476.         case mouseMovedMessage:
  477.             doAdjustCursor(FrontWindow());
  478.             break;
  479.     }
  480. }
  481.  
  482. // **************************************************************************** doNewDocWindow
  483.  
  484. WindowRef  doNewDocWindow(void)
  485. {
  486.     WindowRef                     windowRef;
  487.     docStructurePointer    docStrucPtr;
  488.     Rect                                portRect, destAndViewRect;
  489.     OSErr                                osError;
  490.  
  491.     if(!(windowRef = GetNewCWindow(rWindow,NULL,(WindowRef) -1)))
  492.     {
  493.         doErrorAlert(eWindow);
  494.         return NULL;
  495.     }
  496.  
  497.     SetPortWindowPort(windowRef);
  498.     TextSize(10);
  499.  
  500.     if(!(docStrucPtr = (docStructurePointer) NewPtr(sizeof(docStructure))))
  501.     {
  502.         doErrorAlert(eDocStructure);
  503.         return NULL;
  504.     }
  505.  
  506.     SetWRefCon(windowRef,(SInt32) docStrucPtr);
  507.     SetWindowProxyCreatorAndType(windowRef,0,'TEXT',kUserDomain);
  508.  
  509.     gNumberOfWindows ++;
  510.  
  511.     docStrucPtr->windowRef     = windowRef;
  512.     docStrucPtr->windowTouched = false;
  513.     docStrucPtr->preDragText   = NULL;
  514.     docStrucPtr->vScrollbarRef = GetNewControl(rVScrollbar,windowRef);
  515.  
  516.     GetWindowPortBounds(windowRef,&portRect);
  517.     destAndViewRect = portRect;
  518.     destAndViewRect.right -= 15;
  519.     InsetRect(&destAndViewRect,2,2);
  520.  
  521.     if(!(docStrucPtr->textEditStrucHdl = TENew(&destAndViewRect,&destAndViewRect)))
  522.     {
  523.         DisposeWindow(windowRef);
  524.         gNumberOfWindows --;
  525.         DisposePtr((Ptr) docStrucPtr);
  526.         doErrorAlert(eTextEdit);
  527.         return NULL;
  528.     }
  529.  
  530.     TESetClickLoop(gCustomClickLoopUPP,docStrucPtr->textEditStrucHdl);
  531.     TEAutoView(true,docStrucPtr->textEditStrucHdl);
  532.     TEFeatureFlag(teFOutlineHilite,teBitSet,docStrucPtr->textEditStrucHdl);
  533.  
  534.     if(osError = InstallTrackingHandler(gDragTrackingHandlerUPP,windowRef,docStrucPtr))
  535.     {
  536.         DisposeWindow(windowRef);
  537.         gNumberOfWindows --;
  538.         DisposePtr((Ptr) docStrucPtr);
  539.         doErrorAlert(eDragHandler);
  540.         return NULL;
  541.     }
  542.  
  543.     if(osError = InstallReceiveHandler(gDragReceiveHandlerUPP,windowRef,docStrucPtr))
  544.     {
  545.         RemoveTrackingHandler(gDragTrackingHandlerUPP,windowRef);
  546.         DisposeWindow(windowRef);
  547.         gNumberOfWindows --;
  548.         DisposePtr((Ptr) docStrucPtr);
  549.         doErrorAlert(eDragHandler);
  550.         return NULL;
  551.     }
  552.  
  553.     return windowRef;
  554. }
  555.  
  556. // *************************************************************************** customClickLoop
  557.  
  558. Boolean  customClickLoop(void)
  559. {
  560.     WindowRef                        windowRef;
  561.     docStructurePointer    docStrucPtr;
  562.     TEHandle                        textEditStrucHdl;
  563.     GrafPtr                            oldPort;
  564.     RgnHandle                        oldClip;
  565.     Rect                                tempRect, portRect;
  566.     Point                                mouseXY;
  567.     SInt16                            linesToScroll = 0;
  568.  
  569.     windowRef = FrontWindow();
  570.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));
  571.     textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  572.  
  573.     GetPort(&oldPort);
  574.     SetPortWindowPort(windowRef);
  575.     oldClip = NewRgn();
  576.     GetClip(oldClip);
  577.     SetRect(&tempRect,-32767,-32767,32767,32767);
  578.     ClipRect(&tempRect);
  579.  
  580.     GetMouse(&mouseXY);
  581.     GetWindowPortBounds(windowRef,&portRect);
  582.  
  583.     if(mouseXY.v < portRect.top)
  584.     {
  585.         linesToScroll = 1;
  586.         doSetScrollBarValue(docStrucPtr->vScrollbarRef,&linesToScroll);
  587.         if(linesToScroll != 0)
  588.             TEScroll(0,linesToScroll * ((*textEditStrucHdl)->lineHeight),textEditStrucHdl);
  589.     }
  590.     else if(mouseXY.v > portRect.bottom)
  591.     {
  592.         linesToScroll = -1;
  593.         doSetScrollBarValue(docStrucPtr->vScrollbarRef,&linesToScroll);
  594.         if(linesToScroll != 0)
  595.             TEScroll(0,linesToScroll * ((*textEditStrucHdl)->lineHeight),textEditStrucHdl);
  596.     }
  597.  
  598.     SetClip(oldClip);
  599.     DisposeRgn(oldClip);
  600.     SetPort(oldPort);
  601.  
  602.     return true;
  603. }
  604.  
  605. // *********************************************************************** doSetScrollBarValue
  606.  
  607. void  doSetScrollBarValue(ControlRef controlRef,SInt16 *linesToScroll)
  608. {
  609.     SInt16    controlValue, controlMax;
  610.  
  611.     controlValue = GetControlValue(controlRef);
  612.     controlMax = GetControlMaximum(controlRef);
  613.  
  614.     *linesToScroll = controlValue - *linesToScroll;
  615.     if(*linesToScroll < 0)
  616.         *linesToScroll = 0;
  617.     else if(*linesToScroll > controlMax)
  618.         *linesToScroll = controlMax;
  619.  
  620.     SetControlValue(controlRef,*linesToScroll);
  621.     *linesToScroll = controlValue - *linesToScroll;
  622. }
  623.  
  624. // ***************************************************************************** doAdjustMenus
  625.  
  626. void  doAdjustMenus(void)
  627. {
  628.     MenuRef                            fileMenuRef, editMenuRef;
  629.     WindowRef                        windowRef;
  630.     docStructurePointer    docStrucPtr;
  631.     TEHandle                        textEditStrucHdl;
  632.     ScrapRef                        scrapRef;
  633.     OSStatus                        osError;
  634.     ScrapFlavorFlags        scrapFlavorFlags;
  635.  
  636.     fileMenuRef = GetMenuRef(mFile);
  637.     editMenuRef = GetMenuRef(mEdit);
  638.  
  639.     if(gNumberOfWindows > 0)
  640.     {
  641.         windowRef = FrontWindow();
  642.         docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));;
  643.         textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  644.  
  645.         EnableMenuItem(fileMenuRef,iClose);
  646.  
  647.         if(gEnableDragUndoRedoItem)
  648.         {
  649.             EnableMenuItem(editMenuRef,iUndo);
  650.             if(gUndoFlag)
  651.                 SetMenuItemText(editMenuRef,iUndo,"\pUndo Drag & Drop");
  652.             else
  653.                 SetMenuItemText(editMenuRef,iUndo,"\pRedo Drag & Drop");
  654.         }
  655.         else
  656.         {
  657.             DisableMenuItem(editMenuRef,iUndo);
  658.             SetMenuItemText(editMenuRef,iUndo,"\pRedo Drag & Drop");
  659.         }
  660.  
  661.         if((*textEditStrucHdl)->selStart < (*textEditStrucHdl)->selEnd)
  662.         {
  663.             EnableMenuItem(editMenuRef,iCut);
  664.             EnableMenuItem(editMenuRef,iCopy);
  665.             EnableMenuItem(editMenuRef,iClear);
  666.         }
  667.         else
  668.         {
  669.             DisableMenuItem(editMenuRef,iCut);
  670.             DisableMenuItem(editMenuRef,iCopy);
  671.             DisableMenuItem(editMenuRef,iClear);
  672.         }
  673.  
  674.         GetCurrentScrap(&scrapRef);
  675.  
  676.         osError = GetScrapFlavorFlags(scrapRef,kScrapFlavorTypeText,&scrapFlavorFlags);
  677.         if(osError == noErr)
  678.             EnableMenuItem(editMenuRef,iPaste);
  679.         else
  680.             DisableMenuItem(editMenuRef,iPaste);
  681.  
  682.         if((*textEditStrucHdl)->teLength > 0)
  683.         {
  684.             EnableMenuItem(fileMenuRef,iSaveAs);
  685.             EnableMenuItem(editMenuRef,iSelectAll);
  686.         }
  687.         else
  688.         {
  689.             DisableMenuItem(fileMenuRef,iSaveAs);
  690.             DisableMenuItem(editMenuRef,iSelectAll);
  691.         }
  692.     }
  693.     else
  694.     {
  695.         DisableMenuItem(fileMenuRef,iClose);
  696.         DisableMenuItem(fileMenuRef,iSaveAs);
  697.         DisableMenuItem(editMenuRef,iClear);
  698.         DisableMenuItem(editMenuRef,iSelectAll);
  699.     }
  700.  
  701.     DrawMenuBar();
  702. }
  703.  
  704. // ****************************************************************************** doMenuChoice
  705.  
  706. void  doMenuChoice(SInt32 menuChoice)
  707. {
  708.     MenuID                menuID;
  709.     MenuItemIndex    menuItem;
  710.  
  711.     menuID     = HiWord(menuChoice);
  712.     menuItem = LoWord(menuChoice);
  713.  
  714.     if(menuID == 0)
  715.         return;
  716.  
  717.     switch(menuID)
  718.     {
  719.         case mAppleApplication:
  720.             if(menuItem == iAbout)
  721.                 SysBeep(10);
  722.             break;
  723.  
  724.         case mFile:
  725.             doFileMenu(menuItem);
  726.             break;
  727.  
  728.         case mEdit:
  729.             doEditMenu(menuItem);
  730.             break;
  731.     }
  732.  
  733.     HiliteMenu(0);
  734. }
  735.  
  736. // ******************************************************************************** doFileMenu
  737.  
  738. void    doFileMenu(MenuItemIndex menuItem)
  739. {
  740.     docStructurePointer    docStrucPtr;
  741.     TEHandle                        textEditStrucHdl;
  742.  
  743.     switch(menuItem)
  744.     {
  745.         case iNew:
  746.             doNewDocWindow();
  747.             break;
  748.  
  749.         case iOpen:
  750.             doOpenCommand();
  751.             break;
  752.  
  753.         case iClose:
  754.             doCloseWindow(FrontWindow());
  755.             break;
  756.  
  757.         case iSaveAs:
  758.             docStrucPtr = (docStructurePointer) (GetWRefCon(FrontWindow()));
  759.             textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  760.             doSaveAsFile(textEditStrucHdl);
  761.             break;
  762.  
  763.         case iQuit:
  764.             gDone = true;
  765.             break;
  766.     }
  767. }
  768.  
  769. // ******************************************************************************** doEditMenu
  770.  
  771. void    doEditMenu(MenuItemIndex menuItem)
  772. {
  773.     WindowRef                        windowRef;
  774.     docStructurePointer    docStrucPtr;
  775.     TEHandle                        textEditStrucHdl;
  776.     SInt32                            totalSize, contigSize, newSize;
  777.     SInt16                            selectionLength;
  778.     ScrapRef                        scrapRef;
  779.     Size                                sizeOfTextData;
  780.  
  781.     windowRef = FrontWindow();
  782.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));
  783.     textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  784.  
  785.     switch(menuItem)
  786.     {
  787.         case iUndo:
  788.             doUndoRedoDrag(windowRef);
  789.             break;
  790.  
  791.         case iCut:
  792.             if(ClearCurrentScrap() == noErr)
  793.             {
  794.                 PurgeSpace(&totalSize,&contigSize);
  795.                 selectionLength = doGetSelectLength(textEditStrucHdl);
  796.                 if(selectionLength > contigSize)
  797.                     doErrorAlert(eNoSpaceCut);
  798.                 else
  799.                 {
  800.                     TECut(textEditStrucHdl);
  801.                     doAdjustScrollbar(windowRef);
  802.                     if(TEToScrap() != noErr)
  803.                         ClearCurrentScrap();
  804.                 }
  805.             }
  806.             break;
  807.  
  808.         case iCopy:
  809.             if(ClearCurrentScrap() == noErr)
  810.             {
  811.                 TECopy(textEditStrucHdl);
  812.                 if(TEToScrap() != noErr)
  813.                     ClearCurrentScrap();
  814.             }
  815.             break;
  816.  
  817.         case iPaste:
  818.             GetCurrentScrap(&scrapRef);;
  819.             GetScrapFlavorSize(scrapRef,kScrapFlavorTypeText,&sizeOfTextData);
  820.             newSize = (*textEditStrucHdl)->teLength + sizeOfTextData;
  821.             if(newSize > kMaxTELength)
  822.                 doErrorAlert(eNoSpacePaste);
  823.             else
  824.             {
  825.                 if(TEFromScrap() == noErr)
  826.                 {
  827.                     TEPaste(textEditStrucHdl);
  828.                     doAdjustScrollbar(windowRef);
  829.                 }
  830.             }
  831.             break;
  832.  
  833.         case iClear:
  834.             TEDelete(textEditStrucHdl);
  835.             doAdjustScrollbar(windowRef);
  836.             break;
  837.  
  838.         case iSelectAll:
  839.             TESetSelect(0,(*textEditStrucHdl)->teLength,textEditStrucHdl);
  840.             break;
  841.     }
  842. }
  843.  
  844. // ************************************************************************* doGetSelectLength
  845.  
  846. SInt16  doGetSelectLength(TEHandle textEditStrucHdl)
  847. {
  848.     SInt16    selectionLength;
  849.  
  850.     selectionLength = (*textEditStrucHdl)->selEnd - (*textEditStrucHdl)->selStart;
  851.     return selectionLength;
  852. }
  853.  
  854. // ************************************************************************* doAdjustScrollbar
  855.  
  856. void  doAdjustScrollbar(WindowRef windowRef)
  857. {
  858.     docStructurePointer    docStrucPtr;
  859.     TEHandle                        textEditStrucHdl;
  860.     SInt16                            numberOfLines, controlMax, controlValue;
  861.  
  862.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));;
  863.     textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  864.  
  865.     numberOfLines = (*textEditStrucHdl)->nLines;
  866.     if(*(*(*textEditStrucHdl)->hText + (*textEditStrucHdl)->teLength - 1) == kReturn)
  867.         numberOfLines += 1;
  868.  
  869.     controlMax = numberOfLines - (((*textEditStrucHdl)->viewRect.bottom - 
  870.                              (*textEditStrucHdl)->viewRect.top) /
  871.                              (*textEditStrucHdl)->lineHeight);
  872.     if(controlMax < 0)
  873.         controlMax = 0;
  874.     SetControlMaximum(docStrucPtr->vScrollbarRef,controlMax);
  875.  
  876.     controlValue = ((*textEditStrucHdl)->viewRect.top - (*textEditStrucHdl)->destRect.top) / 
  877.                                     (*textEditStrucHdl)->lineHeight;
  878.     if(controlValue < 0)
  879.         controlValue = 0;
  880.     else if(controlValue > controlMax)
  881.         controlValue = controlMax;
  882.  
  883.     SetControlValue(docStrucPtr->vScrollbarRef,controlValue);
  884.  
  885.     SetControlViewSize(docStrucPtr->vScrollbarRef,(*textEditStrucHdl)->viewRect.bottom - 
  886.                                          (*textEditStrucHdl)->viewRect.top);
  887.  
  888.     TEScroll(0,((*textEditStrucHdl)->viewRect.top - (*textEditStrucHdl)->destRect.top) - 
  889.                              (GetControlValue(docStrucPtr->vScrollbarRef) *
  890.                             (*textEditStrucHdl)->lineHeight),textEditStrucHdl);
  891. }
  892.  
  893. // **************************************************************************** doAdjustCursor
  894.  
  895. void  doAdjustCursor(WindowRef windowRef)
  896. {
  897.     GrafPtr                            oldPort;
  898.     RgnHandle                        arrowRegion, iBeamRegion, hiliteRgn;
  899.     Rect                                portRect, cursorRect;
  900.     docStructurePointer    docStrucPtr;
  901.     Point                                offset, mouseXY;
  902.  
  903.     GetPort(&oldPort);
  904.     SetPortWindowPort(windowRef);
  905.  
  906.     arrowRegion = NewRgn();
  907.     iBeamRegion = NewRgn();
  908.     hiliteRgn        = NewRgn();    
  909.     SetRectRgn(arrowRegion,-32768,-32768,32766,32766);
  910.  
  911.     GetWindowPortBounds(windowRef,&portRect);
  912.     cursorRect = portRect;
  913.     cursorRect.right    -= 15;
  914.     LocalToGlobal(&topLeft(cursorRect));
  915.     LocalToGlobal(&botRight(cursorRect));    
  916.  
  917.     RectRgn(iBeamRegion,&cursorRect);
  918.     DiffRgn(arrowRegion,iBeamRegion,arrowRegion);
  919.  
  920.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));
  921.     TEGetHiliteRgn(hiliteRgn,docStrucPtr->textEditStrucHdl);
  922.     LocalToGlobal(&topLeft(portRect));    
  923.     offset = topLeft(portRect);
  924.     OffsetRgn(hiliteRgn,offset.h,offset.v);
  925.     DiffRgn(iBeamRegion,hiliteRgn,iBeamRegion);
  926.  
  927.     GetGlobalMouse(&mouseXY);
  928.  
  929.     if(PtInRgn(mouseXY,iBeamRegion))
  930.     {
  931.         SetThemeCursor(kThemeIBeamCursor);
  932.         CopyRgn(iBeamRegion,gCursorRegion);
  933.     }
  934.     else if(PtInRgn(mouseXY,hiliteRgn))
  935.     {
  936.         SetThemeCursor(kThemeArrowCursor);
  937.         CopyRgn(hiliteRgn,gCursorRegion);
  938.     }
  939.     else
  940.     {
  941.         SetThemeCursor(kThemeArrowCursor);
  942.         CopyRgn(arrowRegion,gCursorRegion);
  943.     }
  944.  
  945.     DisposeRgn(arrowRegion);
  946.     DisposeRgn(iBeamRegion);
  947.     DisposeRgn(hiliteRgn);
  948.  
  949.     SetPort(oldPort);
  950. }
  951.  
  952. // ***************************************************************************** doCloseWindow
  953.  
  954. void  doCloseWindow(WindowRef windowRef)
  955. {
  956.     docStructurePointer    docStrucPtr;
  957.  
  958.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));;
  959.  
  960.     DisposeControl(docStrucPtr->vScrollbarRef);
  961.     TEDispose(docStrucPtr->textEditStrucHdl);
  962.     DisposePtr((Ptr) docStrucPtr);
  963.  
  964.     if(docStrucPtr->preDragText == NULL)
  965.         DisposeHandle(docStrucPtr->preDragText);
  966.  
  967.     RemoveTrackingHandler(gDragTrackingHandlerUPP,windowRef);
  968.     RemoveReceiveHandler(gDragReceiveHandlerUPP,windowRef);
  969.  
  970.     DisposeWindow(windowRef);
  971.  
  972.     gNumberOfWindows --;
  973. }
  974.  
  975. // ****************************************************************************** doSaveAsFile
  976.  
  977. void  doSaveAsFile(TEHandle textEditStrucHdl)
  978. {
  979.     OSErr                            osError = noErr;
  980.     NavDialogOptions    dialogOptions;
  981.     WindowRef                    windowRef;
  982.     NavEventUPP                navEventFunctionUPP;
  983.     OSType                        fileType;
  984.     NavReplyRecord        navReplyStruc;
  985.     AEKeyword                    theKeyword;
  986.     DescType                    actualType;
  987.     FSSpec                        fileSpec;    
  988.     SInt16                        fileRefNum;
  989.     Size                            actualSize;
  990.     SInt32                        dataLength;
  991.     Handle                        editTextHdl;
  992.         
  993.     osError = NavGetDefaultDialogOptions(&dialogOptions);
  994.  
  995.     if(osError == noErr)
  996.     {
  997.         windowRef = FrontWindow();
  998.  
  999.         fileType = 'TEXT';
  1000.  
  1001.         navEventFunctionUPP = NewNavEventUPP((NavEventProcPtr) navEventFunction);
  1002.         osError = NavPutFile(NULL,&navReplyStruc,&dialogOptions,navEventFunctionUPP,fileType,
  1003.                                                  'kkkB',NULL);
  1004.         DisposeNavEventUPP(navEventFunctionUPP);
  1005.  
  1006.         if(navReplyStruc.validRecord && osError == noErr)
  1007.         {
  1008.             if((osError = AEGetNthPtr(&(navReplyStruc.selection),1,typeFSS,&theKeyword,
  1009.                                                                 &actualType,&fileSpec,sizeof(fileSpec),&actualSize)) == noErr)
  1010.  
  1011.             {
  1012.                 if(!navReplyStruc.replacing)
  1013.                 {
  1014.                     osError = FSpCreate(&fileSpec,'kkkB',fileType,navReplyStruc.keyScript);
  1015.                     if(osError != noErr)
  1016.                     {
  1017.                         NavDisposeReply(&navReplyStruc);
  1018.                     }
  1019.                 }
  1020.                 
  1021.                 if(osError == noErr)
  1022.                     osError = FSpOpenDF(&fileSpec,fsRdWrPerm,&fileRefNum);
  1023.  
  1024.                 if(osError == noErr)
  1025.                 {
  1026.                     SetWTitle(windowRef,fileSpec.name);
  1027.                     dataLength = (*textEditStrucHdl)->teLength;
  1028.                     editTextHdl = (*textEditStrucHdl)->hText;
  1029.                     FSWrite(fileRefNum,&dataLength,*editTextHdl);
  1030.                 }
  1031.  
  1032.                 NavCompleteSave(&navReplyStruc,kNavTranslateInPlace);
  1033.             }
  1034.  
  1035.             NavDisposeReply(&navReplyStruc);
  1036.         }
  1037.     }
  1038. }
  1039.  
  1040. // ***************************************************************************** doOpenCommand
  1041.  
  1042. void  doOpenCommand(void)
  1043. {    
  1044.     OSErr                            osError    = noErr;
  1045.     NavDialogOptions    dialogOptions;
  1046.     NavEventUPP                navEventFunctionUPP;
  1047.     NavReplyRecord        navReplyStruc;
  1048.     SInt32                        index, count;
  1049.     AEKeyword                    theKeyword;
  1050.     DescType                    actualType;
  1051.     FSSpec                        fileSpec;    
  1052.     Size                            actualSize;
  1053.     FInfo                            fileInfo;
  1054.  
  1055.     osError = NavGetDefaultDialogOptions(&dialogOptions);
  1056.  
  1057.     if(osError == noErr)
  1058.     {
  1059.         navEventFunctionUPP = NewNavEventUPP((NavEventProcPtr) navEventFunction);
  1060.         osError = NavGetFile(NULL,&navReplyStruc,&dialogOptions,navEventFunctionUPP,NULL,NULL,
  1061.                                                  NULL,0);
  1062.         DisposeNavEventUPP(navEventFunctionUPP);
  1063.  
  1064.         if(osError == noErr && navReplyStruc.validRecord)
  1065.         {
  1066.             if(osError == noErr)
  1067.             {
  1068.                 osError = AECountItems(&(navReplyStruc.selection),&count);
  1069.  
  1070.                 for(index=1;index<=count;index++)
  1071.                 {
  1072.                     osError = AEGetNthPtr(&(navReplyStruc.selection),index,typeFSS,&theKeyword,
  1073.                                                                 &actualType,&fileSpec,sizeof(fileSpec),&actualSize);
  1074.                     {
  1075.                         if((osError = FSpGetFInfo(&fileSpec,&fileInfo)) == noErr)
  1076.                             doOpenFile(fileSpec);
  1077.                     }
  1078.                 }
  1079.             }
  1080.  
  1081.             NavDisposeReply(&navReplyStruc);    
  1082.         }
  1083.     }
  1084. }
  1085.  
  1086. // ************************************************************************** navEventFunction
  1087.  
  1088. void  navEventFunction(NavEventCallbackMessage callBackSelector,NavCBRecPtr callBackParms,
  1089.                                              NavCallBackUserData callBackUD)
  1090. {
  1091.     WindowRef    windowRef;
  1092.  
  1093.     if(callBackParms != NULL)
  1094.     {
  1095.         switch(callBackSelector)
  1096.         {
  1097.             case kNavCBEvent:
  1098.                 switch(callBackParms->eventData.eventDataParms.event->what)
  1099.                 {
  1100.                     case updateEvt:
  1101.                         windowRef = (WindowRef) callBackParms->eventData.eventDataParms.event->message;
  1102.                         if(GetWindowKind(windowRef) != kDialogWindowKind)
  1103.                             doUpdate((EventRecord *) callBackParms->eventData.eventDataParms.event);
  1104.                         break;
  1105.                 }
  1106.                 break;
  1107.         }
  1108.     }
  1109. }
  1110.  
  1111. // ******************************************************************************** doOpenFile
  1112.  
  1113. void  doOpenFile(FSSpec fileSpec)
  1114. {
  1115.     WindowRef                     windowRef;
  1116.     docStructurePointer    docStrucPtr;
  1117.     TEHandle                        textEditStrucHdl;
  1118.     SInt16                            fileRefNum;
  1119.     SInt32                            textLength;
  1120.     Handle                            textBuffer;
  1121.  
  1122.     if((windowRef = doNewDocWindow()) == NULL)
  1123.         return;
  1124.  
  1125.     docStrucPtr = (docStructurePointer) (GetWRefCon(windowRef));
  1126.     textEditStrucHdl = docStrucPtr->textEditStrucHdl;
  1127.  
  1128.     SetWTitle(windowRef,fileSpec.name);
  1129.  
  1130.     FSpOpenDF(&fileSpec,fsCurPerm,&fileRefNum);
  1131.  
  1132.     SetFPos(fileRefNum,fsFromStart,0);
  1133.     GetEOF(fileRefNum,&textLength);
  1134.  
  1135.     if(textLength > 32767)
  1136.         textLength = 32767;
  1137.  
  1138.     textBuffer = NewHandle((Size) textLength);
  1139.  
  1140.     FSRead(fileRefNum,&textLength,*textBuffer);
  1141.  
  1142.     MoveHHi(textBuffer);
  1143.     HLock(textBuffer);
  1144.  
  1145.     TESetText(*textBuffer,textLength,textEditStrucHdl);
  1146.  
  1147.     HUnlock(textBuffer);
  1148.     DisposeHandle(textBuffer);
  1149.  
  1150.     FSClose(fileRefNum);
  1151.  
  1152.     (*textEditStrucHdl)->selStart = 0;
  1153.     (*textEditStrucHdl)->selEnd = 0;
  1154. }
  1155.  
  1156. // ****************************************************************************** doErrorAlert
  1157.  
  1158. void  doErrorAlert(SInt16 errorCode)
  1159. {
  1160.     Str255    errorString;
  1161.     SInt16    itemHit;
  1162.  
  1163.     GetIndString(errorString,rErrorStrings,errorCode);
  1164.  
  1165.     if(errorCode < eWindow)
  1166.     {
  1167.         StandardAlert(kAlertStopAlert,errorString,NULL,NULL,&itemHit);
  1168.         ExitToShell();
  1169.     }
  1170.     else
  1171.     {
  1172.         StandardAlert(kAlertCautionAlert,errorString,NULL,NULL,&itemHit);
  1173.     }
  1174. }
  1175.  
  1176. // *******************************************************************************************